/**
 * Copyright (C) 2004-2008 Giant Interective Group, Inc. All rights reserved.
 *
 * @(#) DateUtil.java 1.0 2008-09-02
 */
package com.xsoft.web.util;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 日期类数据处理的封装简便类。
 * 
 * @author  FuChun
 * @version 1.0, 2008/10/17
 */
@SuppressWarnings("all")
public class DateUtil {
	
	private final static Logger LOG = LoggerFactory.getLogger(DateUtil.class);

	/** 一秒钟的毫秒数 */
	private final static long MILLI_OF_SECOND = 1000;
	
	/** 一分钟的毫秒数 */
	private final static long MILLI_OF_MINUTE = 60 * MILLI_OF_SECOND;
	
	/** 一小时的毫秒数 */
	private final static long MILLI_OF_HOUR = 60 * MILLI_OF_MINUTE;
	
	/** 一天的毫秒数 */
	private final static long MILLI_OF_DAY = 24 * MILLI_OF_HOUR;
	
	/** 星期的中文表示 */
	private final static String[] WEEKS = {
		// 星期一 ~ 星期天
		"\u661f\u671f\u4e00", "\u661f\u671f\u4e8c", "\u661f\u671f\u4e09", "\u661f\u671f\u56db",
		"\u661f\u671f\u4e94", "\u661f\u671f\u516d", "\u661f\u671f\u5929"
	};
	
	/** 月份的中文表示 */
	private final static String[] MONTHS = {
		"\u4e00  \u6708", "\u4e8c  \u6708",	"\u4e09  \u6708", "\u56db  \u6708",
		"\u4e94  \u6708", "\u516d  \u6708", "\u4e03  \u6708",	"\u516b  \u6708",
		"\u4e5d  \u6708",	"\u5341  \u6708", "\u5341\u4e00\u6708", "\u5341\u4e8c\u6708"
	};
	
	/**
	 * <code>DateUtil</code>类默认的构造方法。
	 */
	DateUtil() {
	}
	
	/**
	 * 计算两个<code>java.util.Date</code>时间之间相差的毫秒数。
	 * 
	 * @param start 第一个<code>java.util.Date</code>时间点。
	 * @param end 第二个<code>java.util.Date</code>时间点。
	 * @return 返回两个<code>java.util.Date</code>时间相差的毫秒数。
	 */
	public static long timespace(java.util.Date start, java.util.Date end) {
		return (end.getTime() - start.getTime());
	}
	
	/**
	 * 计算两个<code>java.util.Date</code>时间之间相差的秒数。
	 * 
	 * @param start 第一个<code>java.util.Date</code>时间点。
	 * @param end 第二个<code>java.util.Date</code>时间点。
	 * @return 返回两个<code>java.util.Date</code>时间相差的秒数。
	 */
	public static double timespaceOfSecond(java.util.Date start, java.util.Date end) {
		BigDecimal diffspace = new BigDecimal(String.valueOf(timespace(start, end)));
		BigDecimal millisecond = new BigDecimal(String.valueOf(MILLI_OF_SECOND));
		return diffspace.divide(millisecond, 3, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	/**
	 * 计算两个<code>java.util.Date</code>时间之间相差的分钟数。
	 * 
	 * @param start 第一个<code>java.util.Date</code>时间点。
	 * @param end 第二个<code>java.util.Date</code>时间点。
	 * @return 返回两个<code>java.util.Date</code>时间相差的分钟数。
	 */
	public static double timespaceOfMinute(java.util.Date start, java.util.Date end) {
		BigDecimal diffspace = new BigDecimal(String.valueOf(timespace(start, end)));
		BigDecimal minute = new BigDecimal(String.valueOf(MILLI_OF_MINUTE));
		return diffspace.divide(minute, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	/**
	 * 计算两个<code>java.util.Date</code>时间之间相差的小时数。
	 * 
	 * @param start 第一个<code>java.util.Date</code>时间点。
	 * @param end 第二个<code>java.util.Date</code>时间点。
	 * @return 返回两个<code>java.util.Date</code>时间相差的小时数。
	 */
	public static double timespaceOfHour(java.util.Date start, java.util.Date end) {
		BigDecimal diffspace = new BigDecimal(String.valueOf(timespace(start, end)));
		BigDecimal hour = new BigDecimal(String.valueOf(MILLI_OF_HOUR));
		return diffspace.divide(hour, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
	}
	
	/**
	 * 计算两个<code>java.util.Date</code>时间之间相差的天数。
	 * 
	 * @param start 第一个<code>java.util.Date</code>时间点。
	 * @param end 第二个<code>java.util.Date</code>时间点。
	 * @return 返回两个<code>java.util.Date</code>时间相差的天数。
	 */
	public static int timespaceOfDay(java.util.Date start, java.util.Date end) {
		BigDecimal diffspace = new BigDecimal(String.valueOf(timespace(start, end)));
		BigDecimal day = new BigDecimal(String.valueOf(MILLI_OF_DAY));
		return diffspace.divide(day, 2, BigDecimal.ROUND_HALF_UP).intValue();
	}
	
	/**
	 * 获取当前日期和时间的<code>java.sql.Timestamp</code>对象。
	 * 
	 * @return 返回 当前的<code>java.sql.Timestamp</code>。
	 */
	public static Timestamp getTimestamp() {
		return new Timestamp(System.currentTimeMillis());
	}
	
	/**
	 * 获取当前日期的字符串表示。
	 * 
	 * @return 返回当前日期和时间的字符串表示。
	 */
	public static String getDate() {
		return format(new java.util.Date(), "yyyy-MM-dd");
	}
	
	/**
	 * 获取当前日期和时间的字符串表示。
	 * 
	 * @return 返回当前日期和时间的字符串表示。
	 */
	public static String getDatetime() {
		return format(new java.util.Date(), "yyyy-MM-dd HH:mm:ss");
	}
	
	/**
	 * 获取当前日期的星期数的中文表示。
	 * 
	 * @return 返回当前日期的星期数。
	 */
	public static String getDay() {
		Calendar instance = Calendar.getInstance();
		switch(instance.get(Calendar.DAY_OF_WEEK)) {
		case Calendar.MONDAY: return WEEKS[0];
		case Calendar.TUESDAY: return WEEKS[1];
		case Calendar.WEDNESDAY: return WEEKS[2];
		case Calendar.THURSDAY: return WEEKS[3];
		case Calendar.FRIDAY: return WEEKS[4];
		case Calendar.SATURDAY: return WEEKS[5];
		case Calendar.SUNDAY: return WEEKS[6];
		default: return "";
		}
	}
	
	/**
	 * 获取当前日期的月份的中文表示。
	 * 
	 * @return 返回当前日期的月份
	 */
	public static String getMonth() {
		Calendar instance = Calendar.getInstance();
		switch(instance.get(Calendar.MONTH)) {
		case Calendar.JANUARY: return MONTHS[0];
		case Calendar.FEBRUARY: return MONTHS[1];
		case Calendar.MARCH: return MONTHS[2];
		case Calendar.APRIL: return MONTHS[3];
		case Calendar.MAY: return MONTHS[4];
		case Calendar.JUNE: return MONTHS[5];
		case Calendar.JULY: return MONTHS[6];
		case Calendar.AUGUST: return MONTHS[7];
		case Calendar.SEPTEMBER: return MONTHS[8];
		case Calendar.OCTOBER: return MONTHS[9];
		case Calendar.NOVEMBER: return MONTHS[10];
		case Calendar.DECEMBER: return MONTHS[11];
		default: return "";
		}
	}
	
	/**
	 * 返回当前年
	 */
	public static int getYear(){
		Calendar cal = Calendar.getInstance();
		return cal.get(Calendar.YEAR);
	}
	
	/**
	 * 格式化给定的<code>java.util.Date</code>日期。
	 * 
	 * @param date 给定的<code>java.util.Date</code>。
	 * @param pattern 格式化模式。
	 * @return 返回格式化的日期字符串。
	 */
	public static String format(Date date, String pattern, Locale locale) {
		if(null==date)return "";
		if(StringUtil.isNullOrEmpty(pattern)) pattern = "yyyy-MM-dd";
		java.text.DateFormat df;
		try {
			df = new java.text.SimpleDateFormat(pattern, locale);
		} catch(IllegalArgumentException e) {
			df = new java.text.SimpleDateFormat("yyyy-MM-dd", locale);
		}
		return df.format(date);
	}
	
	/**
	 * 格式化给定的<code>java.util.Date</code>日期。
	 * 
	 * @param date 给定的<code>java.util.Date</code>。
	 * @param pattern 格式化模式。
	 * @return 返回格式化的日期字符串。
	 */
	public static String format(java.util.Date date, String pattern) {
		return format(date, pattern, Locale.getDefault());
	}
	
	/**
	 * <p>从给定字符串的开始分析文本，以生成一个日期。该方法不使用给定字符串的整个文本。</p>
	 * 
	 * @param input 一个<code>java.lang.String</code>，从其开始处进行分析。
	 * @param pattern 要分析的日期字符串的格式 (etc. yyyy-MM-dd)
	 * @return 分析字符串得到的<code>java.util.Date</code>。
	 */
	public static java.util.Date parseDate(String input, String pattern) {
		java.util.Date date = null;
		try {
			pattern = pattern.replaceAll("[^Y|y|M|m|D|d|H|h|S|s|:|\\s]", "-");
			DateFormat dateFormat = new SimpleDateFormat(pattern);

			if(!"".equals(input) && (input.length() < pattern.length())) {
				input += pattern.substring(input.length()).replaceAll("[YyMmDdHhSs]",
						"0");
			}
			date = dateFormat.parse(input);
		} catch(Exception e) {}
		return date;
	}
	
	/**
	 * 设置 年、月、日、小时、分钟 和 秒 的值。保留其他字段以前的值。
	 * 并返回给定年、月、日、小时、分钟 和 秒的<code>java.util.Date</code>日期对象。
	 * 
	 * @param year 用来设置年份的值。
	 * @param month 用来设置月份的值。Month 值是基于 0 的。例如，0 表示 January。
	 * @param day 用来设置天数的值。
	 * @param hour 用来设置小时数的值。
	 * @param minute 用来设置分钟数的值。
	 * @param second 用来设置秒数的值。
	 * @return 返回给定年、月、日、小时、分钟 和 秒的<code>java.util.Date</code>日期对象。
	 */
	public static java.util.Date getDate(
			int year, int month, int day, int hour, int minute, int second)
	{
		Calendar cal = Calendar.getInstance();
		cal.set(year, month, day, hour, minute, second);
		return cal.getTime();
	}
	
	/**
	 * 根据规则，为给定的日期对象添加或减去指定的分钟数。例如，要从给定的时间减去 60 分钟数，
	 * 可以通过调用以下方法做到这一点：
	 * <pre>
	 * java.util.Date date = new java.util.Date();
	 * DateUtil.addSecond(date, -60);
	 * </pre>
	 * 
	 * @param date 要添加或减去给定时间的日期对象。
	 * @param amount 为日期添加的分钟数。
	 * @return 返回添加或减去后的新日期对象。
	 */
	public static java.util.Date addMinute(java.util.Date date, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, amount);
		return cal.getTime();
	}
	
	/**
	 * 根据规则，为给定的日期对象添加或减去指定的小时数。例如，要从给定的时间添加 1 小时，
	 * 可以通过调用以下方法做到这一点：
	 * <pre>
	 * java.util.Date date = new java.util.Date();
	 * DateUtil.addHour(date, 1);
	 * </pre>
	 * 
	 * @param date 要添加或减去给定时间的日期对象。
	 * @param amount 为日期添加的小时数。
	 * @return 返回添加或减去后的新日期对象。
	 */
	public static java.util.Date addHour(java.util.Date date, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, amount);
		return cal.getTime();
	}
	
	/**
	 * 根据规则，为给定的日期对象添加或减去指定的天数。例如，要从给定的时间减去 5 天，
	 * 可以通过调用以下方法做到这一点：
	 * <pre>
	 * java.util.Date date = new java.util.Date();
	 * DateUtil.addHour(date, -5);
	 * </pre>
	 * 
	 * @param date 要添加或减去给定时间的日期对象。
	 * @param amount 为日期添加的天数。
	 * @return 返回添加或减去后的新日期对象。
	 */
	public static java.util.Date addDay(java.util.Date date, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_MONTH, amount);
		return cal.getTime();
	}
	public static java.util.Date addDay(int amount) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_MONTH, amount);
		return cal.getTime();
	}
	
	/**
	 * 根据规则，为给定的日期对象添加或减去指定的月数。例如，要从给定的时间加 3 个月，
	 * 可以通过调用以下方法做到这一点：
	 * <pre>
	 * java.util.Date date = new java.util.Date();
	 * DateUtil.addHour(date, 3);
	 * </pre>
	 * 
	 * @param date 要添加或减去给定时间的日期对象。
	 * @param amount 为日期添加的月数。
	 * @return 返回添加或减去后的新日期对象。
	 */
	public static java.util.Date addMonth(java.util.Date date, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, amount);
		return cal.getTime();
	}
	
	/**
	 * 根据规则，为给定的日期对象添加或减去指定的年数。例如，要从给定的时间加 1 年，
	 * 可以通过调用以下方法做到这一点：
	 * <pre>
	 * java.util.Date date = new java.util.Date();
	 * DateUtil.addHour(date, 1);
	 * </pre>
	 * 
	 * @param date 要添加或减去给定时间的日期对象。
	 * @param amount 为日期添加的年数。
	 * @return 返回添加或减去后的新日期对象。
	 */
	public static java.util.Date addYear(java.util.Date date, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.YEAR, amount);
		return cal.getTime();
	}
    
    /**
     * 设置 月、日的值。保留其他字段以前的值。
     * 并返回给定年、月、日、小时、分钟 和 秒的<code>java.util.Date</code>日期对象。
     * 
     * @param month 用来设置月份的值。Month 值是基于 0 的。例如，0 表示 January。
     * @param day 用来设置天数的值。
     * @return 返回给定年、月、日、小时、分钟 和 秒的<code>java.util.Date</code>日期对象。
     */
    public static java.util.Date getMonthDate(int month, int day)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, day);
        return cal.getTime();
    }
    /**
     * 转换日期为字符串
     * 
     * @param date
     * @return
     */
    public static String getDateString(java.util.Date date) {
        if (date == null) {
            return null;
        }
        return format(date, "yyyyMMddHHmmss");
    }

    /**
     * 转换日期为字符串
     * 
     * @param date
     * @return
     */
    public static String getDateString3(java.util.Date date) {
        if (date == null) {
            return null;
        }
        return format(date, "yyyyMMdd");
    }
    
    /**
     * 转换日期为字符串2
     * 
     * @param date
     * @return
     */
    public static String getDateString2(java.util.Date date) {
        if (date == null) {
            return null;
        }
        return format(date, "yyyy年MM月dd日 HH:mm:ss");
    }
    
    /**
     * 获取指定日期的起始时间
     */
    public static Date getStartDate(Date date) {
        
        Calendar startDate = Calendar.getInstance();
        startDate.setTime(date);
        startDate.set(Calendar.AM_PM, Calendar.AM);
        startDate.set(Calendar.HOUR, 0);
        startDate.set(Calendar.MINUTE, 0);
        startDate.set(Calendar.SECOND, 0);
        return startDate.getTime();
    }
    
    /**
     * 获取指定日期的结束时间
     */
    public static Date getEndDate(Date date) {
        
        Calendar endDate = Calendar.getInstance();
        endDate.setTime(date);
        endDate.set(Calendar.AM_PM, Calendar.PM);
        endDate.set(Calendar.HOUR, 11);
        endDate.set(Calendar.MINUTE, 59);
        endDate.set(Calendar.SECOND, 59);
        return endDate.getTime();
    }
    
    /**
     * 格式化并国际化给定日期的格式。
     * 
     * <pre>
     * 若给定的日期与当日相同：HH:mm
     * 若给定的日期在当日之前：MM月dd日
     * 若给定的日期在当天之前：yyyy-MM-dd
     * </pre>
     * 
     * @param date 给定的日期（<code>java.util.Date</code>）。
     * @return 返回格式化的日期。
     */
    public static String formatDate(Date date) {
        Calendar now = Calendar.getInstance();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.YEAR) == now.get(Calendar.YEAR)) {
            if (cal.get(Calendar.DAY_OF_MONTH) == now.get(Calendar.DAY_OF_MONTH))
                return DateUtil.format(date, "HH:mm");
            else
                return DateUtil.format(date, "MM-dd");
        } else {
            // yyyy-MM-dd
            return DateUtil.format(date, "yyyy-MM-dd");
        }
    }
    
}
